package com.gagakuai.engine.impl.interceptor;

import com.gagakuai.engine.impl.cfg.ProcessEngineConfigurationImpl;
import com.gagakuai.engine.impl.context.Context;
import com.gagakuai.engine.impl.db.DbSqlSession;
import com.gagakuai.engine.impl.pvm.runtime.AtomicOperation;
import com.gagakuai.engine.impl.runtime.InterpretableExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedList;
import java.util.List;

/*
 * @program: common-starters
 * @description: 命令上下文：使用命令模式，在这里，存放命令需要的统一的参数信息
 * @author: houhong
 * @create: 2023-01-01 22:58
 */
public class CommandContext {


    private static Logger logger = LoggerFactory.getLogger(CommandContext.class);
    protected Command<?> command;

    /*
     * 接下来要执行的原子类
     */
    protected LinkedList<AtomicOperation> newOperations = new LinkedList<>();
    protected ProcessEngineConfigurationImpl processEngineConfiguration;
    //保存异常信息
    protected Throwable exception = null;

    public CommandContext(Command<?> command, ProcessEngineConfigurationImpl processEngineConfiguration) {
        this.command = command;
        this.processEngineConfiguration = processEngineConfiguration;
       /* this.failedJobCommandFactory = processEngineConfiguration.getFailedJobCommandFactory();
        sessionFactories = processEngineConfiguration.getSessionFactories();
        this.transactionContext = processEngineConfiguration
                .getTransactionContextFactory()
                .openTransactionContext(this);*/
    }


    public void performOperation(AtomicOperation operation, InterpretableExecution execution) {

        //将当前操作添加近list
        newOperations.add(operation);

        /*
        *
        * 为了应付子流程？
        */
        if (newOperations.size() == 1) {
            try {
                Context.setExecutionContext(execution);

                while (!newOperations.isEmpty()) {

                    AtomicOperation currentOperation = newOperations.removeFirst();

                    if (logger.isTraceEnabled()) {
                        logger.trace("AtomicOperation: {} on {}", currentOperation, this);
                    }

                    if (execution.getReplacedBy() == null) {
                        currentOperation.execute(execution);
                    } else {
                        currentOperation.execute(execution.getReplacedBy());
                    }
                }

            } finally {
                Context.removeExecutionContext();
            }
        }

    }


    public DbSqlSession getDbSqlSession() {
        return getSession(DbSqlSession.class);
    }

    // // TODO: 2023/1/2
    public static <T> T getSession(Class<T> clazz) {

        return null;
    }


    public Command<?> getCommand() {
        return command;
    }

    public void setCommand(Command<?> command) {
        this.command = command;
    }

    public ProcessEngineConfigurationImpl getProcessEngineConfiguration() {
        return processEngineConfiguration;
    }

    public void setProcessEngineConfiguration(ProcessEngineConfigurationImpl processEngineConfiguration) {
        this.processEngineConfiguration = processEngineConfiguration;
    }

    public Throwable getException() {
        return exception;
    }

    public void setException(Throwable exception) {
        this.exception = exception;
    }
}